﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace sgsBase
{
	/// <summary>
	/// Core User for other applications to use for security
	/// </summary>
	/// Contains a generic DataObject class, has functions that might have database data.
	[Serializable]
	public class SgsUser
	{
		//private DbObject m_user;
		private DbUsrUser _user = new DbUsrUser();
		private SgsSecurity m_security;
		private string m_reason = "";

		public bool FirstLogin = false;
		public bool PasswordCaseSensitive = true;

		#region Properties
		// The base properties for any DataObject class passed in MUST be
		// 0 - int      : Unique ID for the user
		// 1 - string   : Login User Name
		// 2 - string   : Login Password
		// 3 - int      : status field (1 will always mean active)
		// 4 - DateTime : access date field - will get updated on login
		//public DbObject BaseObject
		//{
		//    get { if (m_user == null) m_user = new DbObject(); return m_user; }
		//    set { m_user = value; }
		//}

		public int ID
		{
			get { return _user.UserId; }  //BaseObject.IntAt(0); }
			set
			{
				_user.ClearValues();
				_user.UserId = value;
				_user.Status = 1;
				_user.Select();
				//BaseObject.ClearValues();
				//BaseObject.SetValAt(0, value);
				//BaseObject.Select();
			}
		}

		public string LoginName
		{
			get { return _user.LoginId; }
			set { _user.LoginId = value; }
		}

		public string LoginPassword
		{
			get { return _user.LoginPass; }
			set { _user.LoginPass = value; }
		}

		public int Status
		{
			get { return _user.Status; }
			set { _user.Status = value; }
		}

		public DateTime LastAccess
		{
			get { return _user.DtTouch; }
			set { _user.DtTouch = value; }
		}

		public void Touch()
		{
			if (_user.DtTouch == DateTime.MinValue)
				FirstLogin = true;
			else
				FirstLogin = false;

			_user.DtTouch = DateTime.Now;
			_user.LoggedIn = 1;
			_user.Update();
		}

		public virtual SgsSecurity Security
		{
			get
			{
				if (m_security == null)
				{
					m_security = new SgsSecurity(this);
				}
				return m_security;
			}
		}

		public string Reason
		{
			get
			{
				return m_reason;
			}
			set
			{
				m_reason = value;
			}

		}

		public virtual string FullName
		{
			get
			{
				return _user.Descr; 
			}
			set { _user.Descr = value; }
		}
		#endregion

		public void Update()
		{
			_user.Update();
		}
		/// <summary>
		/// Returns the Primary Security Group for the User
		/// </summary>
		public int SecurityGroup
		{
			get
			{
				DbVwSecXrGroupUser xgu = new DbVwSecXrGroupUser();
				
				xgu.UserId = ID;
				xgu.GroupType = 1;
				if (xgu.Select())
					return xgu.GroupId;

				return 0;
			}
		}

		public SgsUser()
		{
		}

		public virtual string CreateLoginCookie()
		{
			_user.CookieCode = ApplicationHelper.CreateHashCode(15);

			DbUsrUser tmpUser = new DbUsrUser();
			tmpUser.CookieCode = _user.CookieCode;
			if (tmpUser.Select()) //checking to make sure the code does not alrady exist. This is recursive
				return CreateLoginCookie();

			_user.Update();
			return _user.CookieCode;
		}

		/// <summary>
		/// Logs in the username and password passed in
		/// </summary>
		/// <param name="UserID">user name to log in</param>
		/// <param name="Password">password associated with user name</param>
		/// <returns>true if login successful, false otherwise</returns>
		/// this function should attempt logins in the following logical sequence:
		/// 1. Check if the user is in the usr_Users table. If, so the user is valid and has logged in before.
		/// 2. If not in usr_users, check with Integra to see if the user id exists.
		///		if so, create the user locally in the tables and add the integra data to the integra user tables.
		///		otherwise, return false
		public virtual bool Login(string UserName, string Password)
		{
            Logout();

			if (UserName == "" || Password == "")
				return false;
			_user.ClearValues();

			LoginName = UserName;
			Status = 1;

			if (!_user.Select())
			{
				m_reason = "User not found";
				return false;
			}

			// if they were set up by a dealer but have not logged in before, this will occur. 
			if (LoginPassword == "")
			{
				Logout();
				m_reason = "First time Logging In";
				return false;
			}
			if ((PasswordCaseSensitive && LoginPassword != Password) || 
				(PasswordCaseSensitive == false && LoginPassword.ToLower() != Password.ToLower()))
			{
				Logout();
				m_reason = "Password Incorrect";
				return false;
			}

            // user should already be reset from the logout

            UpdateLastLogin();
			return true;
		}

		public virtual bool Login(int UserId)
		{
			Logout();

			_user.ClearValues();

			ID = UserId;
			Status = 1;

			if (!_user.Select())
			{
				m_reason = "User not found";
				return false;
			}

			UpdateLastLogin();
			return true;
		}

		public virtual bool Login(string cookieCode)
		{
			Logout();

			if (cookieCode == ""  || cookieCode == null)
				return false;
			_user.ClearValues();
			_user.CookieCode = cookieCode;
			Status = 1;

			if (!_user.Select())
			{
				m_reason = "User not found";
				return false;
			}

			UpdateLastLogin();
			return true;
		}

		public virtual void NewUserSecurity(int defaultGroup, int UserId, string groupName)
		{
			DbSecXrGroupUser ugx = new DbSecXrGroupUser();

			// make sure userid 0 is not reinserted anywhere
			if (defaultGroup != 0 && UserId != 0) // cannot insert into group 0. this is a hidden visitor group.
			{
				ugx.UserId = UserId;
				ugx.GroupId = defaultGroup;
				ugx.Insert();
			}

			DbSecGroup group = new DbSecGroup();
			group.GroupType = 0;
			group.GroupName = groupName;
			group.Descr = groupName;
			group.Insert();

			ugx.ClearValues();
			ugx.UserId = UserId;
			ugx.GroupId = group.GroupId;
			ugx.Insert();
		}
		public virtual void NewUserSecurity(int defaultGroup)
		{
			NewUserSecurity(defaultGroup, ID, LoginName);
		}
		public virtual void NewUserSecurity(int defaultGroup, string groupName)
		{
			NewUserSecurity(defaultGroup, ID, groupName);
		}
		public virtual void NewUserSecurity(string groupName)
		{
			NewUserSecurity(0, ID, groupName);
		}

		public virtual void Logout()
		{
			Security.Reset();
			if (ID == 0)
			{
				return;
			}
			// set logged out value
			_user.LoggedIn = 0;
			_user.CookieCode = "";
			_user.Update();
			ID = 0;
		}

		public void UpdateLastLogin()
		{
			LastAccess = DateTime.Now;
			Touch();
		}

		public bool ValidateHashCode(string inp)
		{
			//check to see if the hash code is valid against a status of 0
			_user.ClearValues();
			_user.HashCode = inp;
			_user.Status = 0;
			if (!_user.Select())
				return false;

			_user.Status = 1;
			_user.Update();

			//any other request with this email address should be voided out; set status to -1
			string email = _user.Email;
			//_user.ClearValues();

			NewUserSecurity(-1); //set user security to basic user group

			DbInterface dbi = new DbInterface();
			dbi.Query("update usr_users set status=-1 where status=0 and email=" + DbInterface.quote(email));

			return true;
		}
	}
}
